home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / drivers1.zip / DEPCA.ASM < prev    next >
Assembly Source File  |  1992-01-23  |  20KB  |  862 lines

  1. version    equ    2
  2.  
  3. ;  Copyright, 1991-1992, Russell Nelson, Crynwr Software
  4.  
  5. ;   This program is free software; you can redistribute it and/or modify
  6. ;   it under the terms of the GNU General Public License as published by
  7. ;   the Free Software Foundation, version 1.
  8. ;
  9. ;   This program is distributed in the hope that it will be useful,
  10. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. ;   GNU General Public License for more details.
  13. ;
  14. ;   You should have received a copy of the GNU General Public License
  15. ;   along with this program; if not, write to the Free Software
  16. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18.     include    defs.asm
  19.  
  20. NI_CSR        equ    0
  21. RBI        equ    2
  22. DATA_REG    equ    4
  23. ADDR_REG    equ    6
  24.     CSR0        equ    0
  25.     CSR1        equ    1
  26.     CSR2        equ    2
  27.     CSR3        equ    3
  28. EBASE        equ    0ch
  29.  
  30. NI_CSR_VALUE    equ    8ah
  31.  
  32. outport    macro    reg
  33.     push    ax
  34.     setport    ADDR_REG
  35.     mov    ax,reg
  36.     out    dx,ax
  37.     in    ax,dx            ;always follow a write by a read
  38.  
  39.     setport    DATA_REG
  40.     pop    ax
  41.     out    dx,ax
  42.     in    ax,dx            ;always follow a write by a read
  43.  
  44.     endm
  45.  
  46.  
  47. ;
  48. ;     Control and Status Register 0 (CSR0) bit definitions
  49. ;
  50. CSR0_ERR    equ     8000h    ; Error summary
  51. CSR0_BABL    equ     4000h    ; Babble transmitter timeout error
  52. CSR0_CERR    equ    2000h    ; Collision Error
  53. CSR0_MISS    equ    1000h    ; Missed packet
  54. CSR0_MERR    equ    0800h    ; Memory Error
  55. CSR0_RINT    equ    0400h    ; Reciever Interrupt
  56. CSR0_TINT       equ    0200h    ; Transmit Interrupt
  57. CSR0_IDON    equ    0100h    ; Initialization Done
  58. CSR0_INTR    equ    0080h    ; Interrupt Flag
  59. CSR0_INEA    equ    0040h    ; Interrupt Enable
  60. CSR0_RXON    equ    0020h    ; Receiver on
  61. CSR0_TXON    equ    0010h   ; Transmitter on
  62. CSR0_TDMD    equ    0008h    ; Transmit Demand
  63. CSR0_STOP    equ    0004h     ; Stop
  64. CSR0_STRT    equ    0002h    ; Start
  65. CSR0_INIT    equ    0001h    ; Initialize
  66.  
  67. ;
  68. ;     Initialization Block  Mode operation Bit Definitions.
  69. ;
  70. M_PROM        equ    8000h    ; Promiscuous Mode
  71. M_INTL        equ    0040h   ; Internal Loopback
  72. M_DRTY        equ    0020h   ; Disable Retry
  73. M_COLL        equ    0010h    ; Force Collision
  74. M_DTCR        equ    0008h    ; Disable Transmit CRC)
  75. M_LOOP        equ    0004h    ; Loopback
  76. M_DTX        equ    0002h    ; Disable the Transmitter
  77. M_DRX        equ    0001h   ; Disable the Reciever
  78.  
  79.  
  80. ;
  81. ;     Receive message descriptor bit definitions.
  82. ;
  83. RCV_OWN        equ    8000h    ; owner bit 0 = host, 1 = lance
  84. RCV_ERR        equ    4000h    ; Error Summary
  85. RCV_FRAM    equ     2000h    ; Framing Error
  86. RCV_OFLO    equ    1000h    ; Overflow Error
  87. RCV_CRC        equ    0800h    ; CRC Error
  88. RCV_BUF_ERR    equ     0400h    ; Buffer Error
  89. RCV_START    equ    0200h    ; Start of Packet
  90. RCV_END        equ    0100h    ; End of Packet
  91.  
  92.  
  93. ;
  94. ;    Transmit  message descriptor bit definitions.
  95. ;
  96. XMIT_OWN    equ    8000h    ; owner bit 0 = host, 1 = lance
  97. XMIT_ERR    equ    4000h   ; Error Summary
  98. XMIT_RETRY    equ    1000h   ; more the 1 retry needed to Xmit
  99. XMIT_1_RETRY    equ    0800h    ; one retry needed to Xmit
  100. XMIT_DEF    equ    0400h    ; Deferred
  101. XMIT_START    equ    0200h    ; Start of Packet
  102. XMIT_END    equ    0100h    ; End of Packet
  103.  
  104. ;
  105. ;    Miscellaneous Equates
  106. ;
  107.  
  108. TRANSMIT_BUF_COUNT    equ    1
  109. RECEIVE_BUF_COUNT    equ    8
  110. TRANSMIT_BUF_SIZE    equ    1518
  111. RECEIVE_BUF_SIZE    equ    1518
  112.  
  113. ;
  114. ;    Receive Message Descriptor
  115. ;
  116. rcv_msg_dscp struc
  117.     rmd0    dw    ?    ; Rec. Buffer Lo-Address
  118.     rmd1    dw    ?    ; Status bits / Hi-Address
  119.     rmd2    dw    ?    ; Buff Byte-length (2's Comp)
  120.     rmd3    dw    ?    ; Receive message length
  121. rcv_msg_dscp ends
  122.  
  123.  
  124. ;
  125. ;    Transmit Message Descriptor
  126. ;
  127. xmit_msg_dscp struc
  128.     tmd0    dw    ?    ; Xmit Buffer Lo-Address
  129.     tmd1    dw    ?    ; Status bits / Hi-Address
  130.     tmd2     dw    ?    ; Buff Byte-length (2's Comp)
  131.     tmd3    dw    ?    ; Buffer Status bits & TDR value
  132. xmit_msg_dscp ends
  133.  
  134. lance_seg    segment at 0
  135.  
  136. ;
  137. ;the LANCE requires that the descriptor pointers be on a qword boundary.
  138. ;
  139.     align    8
  140.  
  141. transmit_dscps    xmit_msg_dscp    TRANSMIT_BUF_COUNT dup(<>)
  142. receive_dscps    rcv_msg_dscp    RECEIVE_BUF_COUNT dup(<>)
  143.  
  144. ;
  145. ;      LANCE Initialization Block
  146. ;
  147.     align    2
  148. init_block        label    byte
  149. init_mode        dw    0
  150. init_addr        db    EADDR_LEN dup(?)    ; Our Ethernet address
  151. init_filter        db    8 dup(0)    ;Multicast filter.
  152. init_receive        dw    ?,?        ;Receive Ring Pointer.
  153. init_transmit          dw    ?,?          ;Transmit Ring Pointer.
  154.  
  155. transmit_bufs    equ    $
  156. receive_bufs    equ    transmit_bufs + TRANSMIT_BUF_COUNT * TRANSMIT_BUF_SIZE
  157.  
  158. lance_seg    ends
  159.  
  160. code    segment    para public
  161.     assume    cs:code, ds:code
  162.  
  163.         public    int_no
  164. int_no        db    2,0,0,0            ;must be four bytes long for get_number.
  165. io_addr        dw    -1,-1
  166. base_addr    dw    -1,-1
  167.  
  168.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  169. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec
  170. driver_type    db    66        ;from the packet spec
  171. driver_name    db    'DEPCA',0    ;name of the driver.
  172. driver_function    db    2        ;basic, extended
  173. parameter_list    label    byte
  174.     db    1    ;major rev of packet driver
  175.     db    9    ;minor rev of packet driver
  176.     db    14    ;length of parameter list
  177.     db    EADDR_LEN    ;length of MAC-layer address
  178.     dw    GIANT    ;MTU, including MAC headers
  179.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  180.     dw    RECEIVE_BUF_COUNT-1    ;(# of back-to-back MTU rcvs) - 1
  181.     dw    TRANSMIT_BUF_COUNT-1    ;(# of successive xmits) - 1
  182. int_num    dw    0    ;Interrupt # to hook for post-EOI
  183.             ;processing, 0 == none,
  184.  
  185.     public    rcv_modes
  186. rcv_modes    dw    7        ;number of receive modes in our table.
  187.         dw    0               ;There is no mode zero
  188.         dw    0        ;none at all.
  189.         dw    0        ;only ours.
  190.         dw    rcv_mode_3    ;ours plus broadcast
  191.         dw    0        ;some multicasts
  192.         dw    0        ;all multicasts
  193.         dw    0        ;all packets
  194.  
  195. transmit_head    dw    transmit_dscps    ;->next packet to be filled by host.
  196. receive_head    dw    receive_dscps    ;->next packet to be filled by LANCE.
  197.  
  198.     public    as_send_pkt
  199. ; The Asynchronous Transmit Packet routine.
  200. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  201. ;   interrupts possibly enabled.
  202. ; Exit with nc if ok, or else cy if error, dh set to error number.
  203. ;   es:di and interrupt enable flag preserved on exit.
  204. as_send_pkt:
  205.     ret
  206.  
  207.     public    drop_pkt
  208. ; Drop a packet from the queue.
  209. ; Enter with es:di -> iocb.
  210. drop_pkt:
  211.     assume    ds:nothing
  212.     ret
  213.  
  214.     public    xmit
  215. ; Process a transmit interrupt with the least possible latency to achieve
  216. ;   back-to-back packet transmissions.
  217. ; May only use ax and dx.
  218. xmit:
  219.     assume    ds:nothing
  220.     ret
  221.  
  222.  
  223.     public    send_pkt
  224. send_pkt:
  225. ;enter with ds:si -> packet, cx = packet length.
  226. ;exit with nc if ok, or else cy if error, dh set to error number.
  227.     assume    ds:nothing
  228.     mov    es,base_addr
  229.     assume    es:lance_seg
  230.  
  231.     xor    bx,bx
  232.  
  233.     mov    ax,18
  234.     call    set_timeout
  235. send_pkt_1:
  236.     test    transmit_dscps[bx].tmd1,XMIT_OWN    ;Did the lance chip give it back?
  237.     je    send_pkt_2
  238.     call    do_timeout
  239.     jne    send_pkt_1
  240.     mov    dh,CANT_SEND
  241.     stc
  242.     ret
  243. send_pkt_2:
  244. ;reset error indications.
  245.     and    transmit_dscps[bx].tmd1,not (XMIT_ERR or XMIT_DEF or XMIT_1_RETRY or XMIT_RETRY)    ;Did the lance chip give it back?
  246.     mov    transmit_dscps[bx].tmd3,0    ;reset all error bits.
  247.  
  248.     mov    ax,cx            ;store the count.
  249.     cmp    ax,RUNT            ; minimum length for Ether
  250.     ja    oklen
  251.     mov    ax,RUNT            ; make sure size at least RUNT
  252. oklen:
  253.     neg    ax
  254.     mov    transmit_dscps[bx].tmd2,ax    ;store the negative of the cnt.
  255.  
  256.     mov    ax,transmit_dscps[bx].tmd0    ;store the packet.
  257.     mov    dx,transmit_dscps[bx].tmd1
  258.     call    phys_to_segmoffs
  259.     assume    es:nothing
  260.     rep    movsb
  261.  
  262.     mov    es,base_addr
  263.     assume    es:lance_seg
  264.     or    transmit_dscps[bx].tmd1,XMIT_OWN    ;give it to the lance chip.
  265.  
  266. ;Inform LANCE that it should poll for a packet.
  267.     loadport
  268.     mov    ax,CSR0_INEA or CSR0_TDMD
  269.     outport    CSR0
  270.     clc
  271.     ret
  272.  
  273.  
  274. detect_board:
  275. ;test to see if a board is located at io_addr.
  276. ;setup to read first byte of ethernet address rom when successful.
  277. ;return nz if not.
  278.     assume    cs:code, ds:code
  279.  
  280.     loadport
  281.     setport    NI_CSR            ;enable the rev. E DEPCA card.
  282.     mov    al,8
  283.     out    dx,al
  284.     setport    EBASE            ;is it in this port?
  285.     call    detect_port
  286.     je    detect_board_1        ;yup!
  287.     setport    EBASE+1            ;look on the next port for rev. E
  288.     call    detect_port
  289. detect_board_1:
  290.     pushf                ;preserve the result.
  291.     loadport
  292.     setport    NI_CSR            ;restore the NI_CSR contents.
  293.     mov    al,NI_CSR_VALUE
  294.     out    dx,al
  295.     popf
  296.     ret
  297.  
  298.  
  299. depca_pattern    db    0FFh, 00h, 55h, 0AAh, 0FFh, 00h, 55h, 0AAh
  300.  
  301. detect_port:
  302. ;enter with dx = port to read from, looking for depca_pattern.
  303. ;exit with zr if we found it, nz if not.
  304.     mov    cx,32+8            ;do 32 reps, plus look at 8 to match.
  305.     mov    di,0            ;start at the beginning of the string.
  306. detect_port_1:
  307.     in    al,dx            ;input byte.
  308.     cmp    al,depca_pattern[di]    ;do they match?
  309.     jne    detect_port_2        ;no, try again.
  310.     inc    di            ;yes, look at another character.
  311.     cmp    di, 8            ;need to match eight chars.
  312.     jne    short detect_port_3
  313.     ret
  314. detect_port_2:
  315.     xor    di,di            ;start at the beginning of the pattern.
  316. detect_port_3:
  317.     loop    detect_port_1
  318.     or    sp,sp            ;return nz.
  319.     ret
  320.  
  321.  
  322.     public    get_address
  323. get_address:
  324. ;get the address of the interface.
  325. ;enter with es:di -> place to get the address, cx = size of address buffer.
  326. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  327.     assume    ds:code, es:nothing
  328.     cmp    cx,EADDR_LEN        ;make sure that we have enough room.
  329.     jb    get_address_2
  330.     push    di
  331.     call    detect_board
  332.     pop    di
  333.     mov    cx,EADDR_LEN
  334.     loadport            ; Get our Ethernet address base.
  335.     setport    EBASE
  336.     cld
  337. get_address_1:
  338.     in    al,dx            ; get a byte of the eprom address
  339.     stosb
  340.     loop    get_address_1        ; go back for rest
  341.     mov    cx,EADDR_LEN
  342.     clc
  343.     ret
  344. get_address_2:
  345.     stc
  346.     ret
  347.  
  348.  
  349.     public    set_address
  350. set_address:
  351. ;enter with ds:si -> Ethernet address, CX = length of address.
  352. ;exit with nc if okay, or cy, dh=error if any errors.
  353.     assume    ds:nothing
  354.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  355.     je    set_address_4
  356.     mov    dh,BAD_ADDRESS
  357.     stc
  358.     jmp    short set_address_done
  359. set_address_4:
  360.  
  361.     mov    es,base_addr
  362.     mov    di,offset init_addr
  363.     rep    movsb
  364.     call    initialize        ;initialize with our new address.
  365.  
  366. set_address_okay:
  367.     mov    cx,EADDR_LEN        ;return their address length.
  368.     clc
  369. set_address_done:
  370.     push    cs
  371.     pop    ds
  372.     assume    ds:code
  373.     ret
  374.  
  375.  
  376. rcv_mode_1:
  377.     mov    ax,M_DRX or M_DTX    ;disable the receiver and transmitter.
  378.     jmp    initialize_nomulti
  379. rcv_mode_3:
  380.     xor    ax,ax            ;don't accept any multicast frames.
  381.     call    initialize_multi
  382.     mov    ax,0            ;non-promiscuous mode
  383.     jmp    short initialize_nomulti
  384. rcv_mode_5:
  385.     mov    ax,-1            ;accept any multicast frames.
  386.     call    initialize_multi
  387.     mov    ax,0            ;non-promiscuous mode
  388.     jmp    short initialize_nomulti
  389. rcv_mode_6:
  390.     mov    ax,M_PROM    ;promiscuous mode
  391. initialize_nomulti:
  392.     mov    es,base_addr
  393.     mov    es:init_mode,ax
  394.  
  395. initialize:
  396.     loadport
  397.     mov    ax,CSR0_STOP        ;reset the INIT bit.
  398.     outport    CSR0
  399.  
  400.     mov    ax,CSR0_INEA or CSR0_STRT or CSR0_INIT    ;reinit and restart.
  401.     outport    CSR0
  402.  
  403.     setport    DATA_REG
  404.  
  405.     mov    ax,36            ;wait one second for the board
  406.     call    set_timeout        ;  to timeout.
  407. initialize_1:
  408.     in    ax,dx
  409.     test    ax,CSR0_IDON
  410.     jne    initialize_2
  411.     call    do_timeout
  412.     jne    initialize_1
  413.     stc
  414.     ret
  415. initialize_2:
  416.     clc
  417.     ret
  418.  
  419.  
  420. initialize_multi:
  421. ;enter with ax = value for all multicast hash bits.
  422.     mov    es,base_addr
  423.     mov    di,offset init_filter
  424.     mov    cx,8/2
  425.     rep    stosw
  426.     ret
  427.  
  428.  
  429.     public    set_multicast_list
  430. set_multicast_list:
  431. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  432. ;return nc if we set all of them, or cy,dh=error if we didn't.
  433.     mov    dh,NO_MULTICAST        ;for some reason we can't do multi's.
  434.     stc
  435.     ret
  436.  
  437.  
  438.     public    terminate
  439. terminate:
  440.     call    rcv_mode_1        ;don't receive any apckets.
  441.  
  442.     ret
  443.  
  444.     public    reset_interface
  445. reset_interface:
  446. ;reset the interface.
  447.     assume    ds:code
  448.     ret
  449.  
  450.  
  451. ;called when we want to determine what to do with a received packet.
  452. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  453.     extrn    recv_find: near
  454.  
  455. ;called after we have copied the packet into the buffer.
  456. ;enter with ds:si ->the packet, cx = length of the packet.
  457.     extrn    recv_copy: near
  458.  
  459.     extrn    count_in_err: near
  460.     extrn    count_out_err: near
  461.  
  462. LANCE_ISR_ACKNOWLEDGE equ (CSR0_INEA or CSR0_TDMD or CSR0_STOP or CSR0_STRT or CSR0_INIT)
  463.  
  464.     public    recv
  465. recv:
  466. ;called from the recv isr.  All registers have been saved, and ds=cs.
  467. ;Upon exit, the interrupt will be acknowledged.
  468.     assume    ds:code
  469.  
  470.     loadport
  471.     setport    ADDR_REG
  472.     mov    ax,CSR0
  473.     out    dx,ax
  474.     in    ax,dx
  475.     setport    DATA_REG
  476.     in    ax,dx
  477.     mov    bx,ax            ;make a copy.
  478.  
  479. ; Acknowledge the Interrupt from the controller, but disable further
  480. ; controller Interrupts until we service the current interrupt.
  481. ;
  482. ;(CSR0_INEA or CSR0_TDMD or CSR0_STOP or CSR0_STRT or CSR0_INIT)
  483. ;
  484.     and    ax,not LANCE_ISR_ACKNOWLEDGE
  485.     out    dx,ax
  486.     in    ax,dx        ; follow all writes by a read
  487.  
  488.     test    bx,CSR0_RINT        ;receive interrupt?
  489.     jne    recv_RINT        ;yes.
  490.     jmp    recv_done        ;no, we're done.
  491. recv_RINT:
  492.  
  493.     mov    es,base_addr
  494.     assume    es:lance_seg
  495.     mov    bx,receive_head
  496.  
  497. recv_search:
  498.     test    lance_seg:[bx].rmd1,RCV_OWN    ;do we own this buffer?
  499.     je    recv_own        ;yes - process it.
  500.     call    inc_recv_ring        ;go to the next one.
  501.     cmp    bx,receive_head        ;did we get back to the beginning?
  502.     jne    recv_search        ;not yet.
  503.     jmp    recv_done        ;yes -- spurious interrupt!
  504. recv_own:
  505.     test    lance_seg:[bx].rmd1,RCV_ERR    ;Any errors in this buffer?
  506.     jne    recv_err        ;yes -- ignore this packet.
  507.  
  508.     mov    cx,lance_seg:[bx].rmd3
  509.     and    cx,0fffh        ;strip off the reserved bits
  510.  
  511.     mov    ax,lance_seg:[bx].rmd0    ;fetch the packet.
  512.     mov    dx,lance_seg:[bx].rmd1
  513.     call    phys_to_segmoffs
  514.     assume    es:nothing
  515.  
  516.     push    es
  517.     push    di
  518.     push    bx
  519.  
  520.     add    di,EADDR_LEN+EADDR_LEN    ;skip the ethernet addreses and
  521.                     ;  point to the packet type.
  522.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  523.     mov    ax, es:[di]
  524.     xchg    ah, al
  525.     cmp     ax, 1500
  526.     ja    BlueBookPacket
  527.     inc    di            ;set di to 802.2 header
  528.     inc    di
  529.     mov    dl, IEEE8023
  530. BlueBookPacket:
  531.     push    cx
  532.     call    recv_find
  533.     pop    cx
  534.  
  535.     pop    bx
  536.     pop    si
  537.     pop    ds
  538.     assume    ds:nothing, es:nothing
  539.  
  540.     mov    ax,es            ;is this pointer null?
  541.     or    ax,di
  542.     je    recv_free        ;yes - just free the frame.
  543.  
  544.     push    es
  545.     push    di
  546.     push    cx
  547.     rep    movsb
  548.     pop    cx
  549.     pop    si
  550.     pop    ds
  551.     assume    ds:nothing
  552.  
  553.     call    recv_copy
  554.  
  555.     jmp    short recv_free
  556.  
  557. recv_err:
  558.     call    count_in_err
  559. recv_free:
  560.     push    cs
  561.     pop    ds
  562.     assume    ds:code
  563.     mov    es,base_addr
  564.     assume    es:lance_seg
  565.  
  566. ;clear any error bits.
  567.     and    lance_seg:[bx].rmd1,not (RCV_ERR or RCV_FRAM or RCV_OFLO or RCV_CRC or RCV_BUF_ERR)
  568.     or    lance_seg:[bx].rmd1,RCV_OWN    ;give it back to the lance.
  569.     call    inc_recv_ring            ;go to the next one.
  570.     test    lance_seg:[bx].rmd1,RCV_OWN    ;Do we own this one?
  571.     je    recv_own
  572.     mov    receive_head,bx        ;remember where the next one starts.
  573. recv_done:
  574.     loadport            ;enable interrupts again.
  575.     setport    DATA_REG
  576.     mov    ax,CSR0_INEA
  577.     out    dx,ax
  578.  
  579.     ret
  580.  
  581.  
  582. inc_recv_ring:
  583. ;advance bx to the next receive ring descriptor.
  584.     assume    ds:nothing
  585.     add    bx,(size rcv_msg_dscp)
  586.     cmp    bx,offset receive_dscps + RECEIVE_BUF_COUNT * (size rcv_msg_dscp)
  587.     jb    inc_recv_ring_1
  588.     mov    bx,offset receive_dscps
  589. inc_recv_ring_1:
  590.     ret
  591.  
  592.  
  593.     public    recv_exiting
  594. recv_exiting:
  595. ;called from the recv isr after interrupts have been acknowledged.
  596. ;Only ds and ax have been saved.
  597.     assume    ds:nothing
  598.     ret
  599.  
  600.  
  601. phys_to_segmoffs:
  602. ;enter with dx:ax as the physical address of the buffer,
  603. ;exit with es:di -> buffer.
  604.     assume    ds:nothing
  605.   if 0
  606.     shl    dx,16-4            ;move the upper four bits into position.
  607.     mov    di,ax            ;now get the low 12 bits of the segment.
  608.     shr    di,4
  609.     or    dx,di            ;combine them.
  610.     mov    es,dx
  611.     mov    di,ax
  612.     and    di,0fh            ;now compute the offset.
  613.   else
  614.     mov    es,base_addr
  615.     mov    di,ax
  616.   endif
  617.     ret
  618.  
  619.     include    timeout.asm
  620.  
  621. end_resident    label    byte
  622.  
  623.  
  624.     public    usage_msg
  625. usage_msg    db    "usage: depca [-n] [-d] [-w] <packet_int_no> <int_no> <io_addr> <mem_addr>",CR,LF,'$'
  626. no_board_msg    db    "No DEPCA detected.",CR,LF,'$'
  627. io_addr_funny_msg    label    byte
  628.         db    "No DEPCA detected, continuing anyway.",CR,LF,'$'
  629. bad_reset_msg    db    "Unable to reset the DEPCA.",CR,LF,'$'
  630. bad_init_msg    db    "Unable to initialize the DEPCA.",CR,LF,'$'
  631.  
  632.     public    copyright_msg
  633. copyright_msg    db    "Packet driver for a Digital Equipment Corporation DEPCA, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
  634.         db    '$'
  635.  
  636. int_no_name    db    "Interrupt number ",'$'
  637. io_addr_name    db    "I/O port ",'$'
  638. base_addr_name    db    "Memory address ",'$'
  639.  
  640.     extrn    set_recv_isr: near
  641.     extrn    maskint: near
  642.  
  643. ;enter with si -> argument string, di -> dword to store.
  644. ;if there is no number, don't change the number.
  645.     extrn    get_number: near
  646.  
  647. ;enter with dx -> name of word, di -> dword to print.
  648.     extrn    print_number: near
  649.  
  650.     public    parse_args
  651. parse_args:
  652. ;exit with nc if all went well, cy otherwise.
  653.     assume    ds:code
  654.     mov    di,offset int_no
  655.     call    get_number
  656.     mov    di,offset io_addr
  657.     call    get_number
  658.     mov    di,offset base_addr
  659.     call    get_number
  660.     clc
  661.     ret
  662.  
  663.  
  664.     public    etopen
  665. etopen:
  666.     assume    ds:code
  667.  
  668.     cmp    io_addr,-1        ;Did they ask for auto-detect?
  669.     je    find_board
  670.  
  671.     call    detect_board        ;no, just verify its existance.
  672.     je    find_board_found
  673.  
  674.     mov    dx,offset io_addr_funny_msg
  675.     mov    ah,9
  676.     int    21h
  677.  
  678.     jmp    find_board_found
  679.  
  680. find_board:
  681.     mov    io_addr,300h        ;Search for the Ethernet address at 300h
  682.     mov    io_addr+2,0
  683.     call    detect_board
  684.     je    find_board_found
  685.     mov    io_addr,200h        ;Search at 200h
  686.     call    detect_board
  687.     je    find_board_found
  688.  
  689.     mov    dx,offset no_board_msg    ;Tell them that we can't find it.
  690.     mov    ah,9
  691.     int    21h
  692.  
  693.     stc
  694.     ret
  695. find_board_found:
  696.  
  697.     mov    al, int_no        ; Get board's interrupt vector
  698.     add    al, 8
  699.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  700.     jb    set_int_num        ; No.
  701.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  702. set_int_num:
  703.     xor    ah, ah            ; Clear high byte
  704.     mov    int_num, ax        ; Set parameter_list int num.
  705.  
  706.     mov    al,int_no
  707.     call    maskint            ;disable these interrupts.
  708.  
  709.     loadport
  710.     mov    ax,CSR0_STOP        ;reset the INIT bit.
  711.     outport    CSR0
  712.  
  713. ;set up transmit descriptor ring.
  714.     mov    es,base_addr
  715.     assume    es:lance_seg
  716.     mov    cx,TRANSMIT_BUF_COUNT
  717.     mov    bx,offset transmit_dscps
  718.     mov    di,offset transmit_bufs
  719. setup_transmit:
  720.     call    segmoffs_to_phys
  721.  
  722.     or    dx,XMIT_START or XMIT_END
  723.     mov    lance_seg:[bx].tmd0,ax        ;points to the buffer.
  724.     mov    lance_seg:[bx].tmd1,dx
  725.  
  726.     add    bx,(size xmit_msg_dscp)
  727.     add    di,TRANSMIT_BUF_SIZE
  728.     loop    setup_transmit
  729.  
  730. ;set up receive descriptor ring.
  731.     mov    cx,RECEIVE_BUF_COUNT
  732.     mov    bx,offset receive_dscps
  733.     mov    di,offset receive_bufs
  734. setup_receive:
  735.     call    segmoffs_to_phys
  736.  
  737.     or    dx,RCV_OWN
  738.     mov    lance_seg:[bx].rmd0,ax        ;points to the buffer.
  739.     mov    lance_seg:[bx].rmd1,dx
  740.  
  741.     mov    lance_seg:[bx].rmd2,-RECEIVE_BUF_SIZE
  742.     mov    lance_seg:[bx].rmd3,0
  743.  
  744.     add    bx,(size rcv_msg_dscp)
  745.     add    di,RECEIVE_BUF_SIZE
  746.     loop    setup_receive
  747.  
  748. ;initialize the board.
  749.     mov    cx,EADDR_LEN        ;get our address.
  750.     mov    di,offset init_addr
  751.     call    get_address
  752.  
  753.     mov    cx,RECEIVE_BUF_COUNT
  754.     call    compute_log2
  755.  
  756.     mov    di,offset receive_dscps
  757.     call    segmoffs_to_phys
  758.     or    dx,cx            ;include the buffer size bits.
  759.     mov    init_receive[0],ax
  760.     mov    init_receive[2],dx
  761.  
  762.     mov    cx,TRANSMIT_BUF_COUNT
  763.     call    compute_log2
  764.  
  765.     mov    di,offset transmit_dscps
  766.     call    segmoffs_to_phys
  767.     or    dx,cx            ;include the buffer size bits.
  768.     mov    init_transmit[0],ax
  769.     mov    init_transmit[2],dx
  770.  
  771.     mov    di,offset init_block    ;now tell the board where the init
  772.     call    segmoffs_to_phys    ;  block is.
  773.  
  774.     push    dx
  775.     push    ax
  776.  
  777.     loadport
  778.     mov    ax,2            ;write the bus config register.
  779.     outport    CSR3
  780.  
  781.     pop    ax            ;write the low word.
  782.     outport    CSR1
  783.  
  784.     pop    ax            ;write the high word.
  785.     outport    CSR2
  786.  
  787.     call    rcv_mode_3
  788.     jnc    init_ok
  789.  
  790.     mov    dx,offset bad_init_msg
  791.     mov    ah,9
  792.     int    21h
  793.  
  794.     stc
  795.     ret
  796.  
  797. init_ok:
  798. ;
  799. ; Now hook in our interrupt
  800. ;
  801.     call    set_recv_isr
  802.  
  803.     loadport
  804.     setport    NI_CSR
  805.     mov    al,NI_CSR_VALUE        ;disable ROM, enable rev. E DEPCA,
  806.                     ;  enable the interrupt line,
  807.     out    dx,al
  808.  
  809.     mov    dx,offset end_resident
  810.     clc
  811.     ret
  812.  
  813.     public    print_parameters
  814. print_parameters:
  815. ;echo our command-line parameters
  816.     mov    di,offset int_no
  817.     mov    dx,offset int_no_name
  818.     call    print_number
  819.     mov    di,offset io_addr
  820.     mov    dx,offset io_addr_name
  821.     call    print_number
  822.     mov    di,offset base_addr
  823.     mov    dx,offset base_addr_name
  824.     call    print_number
  825.     ret
  826.  
  827. compute_log2:
  828. ;enter with cx = number of buffers.
  829. ;exit with cx = log2(number of buffers) << 13.
  830.     mov    ax,-1
  831. compute_log2_1:
  832.     inc    ax
  833.     shr    cx,1
  834.     jne    compute_log2_1
  835.     mov    cl,13
  836.     shl    ax,cl
  837.     mov    cx,ax
  838.     ret
  839.  
  840.  
  841. segmoffs_to_phys:
  842. ;enter with es:di -> buffer.
  843. ;exit with dx:ax as the physical address of the buffer,
  844.  
  845.   if 0    ; The DEPCA doesn't use system memory, it uses its own.
  846.     mov    dx,es            ;get the high 4 bits of the segment,
  847.     shr    dx,16-4
  848.     mov    ax,es            ;and the low 12 bits of the segment.
  849.     shl    ax,4
  850.     add    ax,di            ;add in the offset.
  851.     adc    dx,0
  852.   else
  853.     xor    dx,dx            ;the offset is the only part of the
  854.     mov    ax,di            ;  address.
  855.   endif
  856.     ret
  857.  
  858.  
  859. code    ends
  860.  
  861.     end
  862.